package com.ihr360.expr.core;

import com.ihr360.expr.ExprException;
import com.ihr360.expr.context.IEvaluationContext;

public class ExprFunction extends ExprEvaluatable {
    private String name;
    private Expr[] args;
    private Object annotation;
    private IExprFunction implementation;

    public ExprFunction(String name, Expr[] args) {
        super(ExprType.Function);
        this.name = name;
        this.args = args;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public Expr getArg(int index) {
        return args[index];
    }
    public Expr[] getArgs() {
        return args;
    }

    public void setArgs(Expr[] args) {
        this.args = args;
    }

    public Object getAnnotation() {
        return annotation;
    }

    public void setAnnotation(Object annotation) {
        this.annotation = annotation;
    }

    public IExprFunction getImplementation() {
        return implementation;
    }

    public void setImplementation(IExprFunction implementation) {
        this.implementation = implementation;
    }

    @Override
    public Expr evaluate(IEvaluationContext context) throws ExprException {
        if (implementation != null) {
            return implementation.evaluate(null, args);
        } else {
            return context.evaluateFunction(this);
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(name);
        sb.append("(");
        for (int i = 0; i < args.length; i++) {
            if (i > 0)
                sb.append(",");
            sb.append(args[i]);
        }
        sb.append(")");
        return sb.toString();
    }

    public void validate() throws ExprException {
        if (name == null)
            throw new ExprException("Function name cannot be empty");
        for (int i = 0; i < args.length; i++) {
            args[i].validate();
        }
    }
}